
#ifndef COMMUNICATOR_H_
#define COMMUNICATOR_H_

#include "MessageDef.h"
#include <stdbool.h>
#include "logger.h"

#include <iostream>
#include <vector>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>

#include <pthread.h>
#include "errno.h"


class Communicator
{
public:
	Communicator();
	virtual ~Communicator();

	// To initialise ports
	bool Initialize(NODE_INFO &NodeInfo, vector<NEIGBOUR_INFO> &vecNeighbourInfo, CLogger *logger);

	// To start Communication -- Receiver thread
	bool StartCommunicator();

	//	Function to create and send Acks
	void SendACK(int nSeqNo, int nAckType, int nDestinationID);
	// Function to send data
	bool SendUDP(int Clientsockfd, char* data, int nLength, NEIGBOUR_INFO NeighbourInfo);

	// Function to receive data
	void ProcessIncomingMessage(char strReceivedData[], int nDataLength);

	// Function to handle Update and its ACK
	void HandleUpdateMessageEx(MESSAGE oMessage);
	void HandleUpdateAckMessage(MESSAGE oMessage);

	// Function to handle Withdraw and its ACK
	void HandleWithdrawMessage(MESSAGE oMessage);
	void HandleWithdrawAckMessage(MESSAGE oMessage);

	// Function to handle Data and its ACK
	void HandleDataMessage(MESSAGE oMessage);
	void HandleDataAckMessage(MESSAGE oMessage);

	// Function to handle GatewayInfo and its ACK
	void HandleGatewayInfoMessageEx(MESSAGE oMessage);
	void HandleGatewayInfoAckMessage(MESSAGE oMessage);

	// Function to handle Hello and its ACK
	void HandleHelloMessage(MESSAGE oMessage);
	void HandleHelloAckMessage(MESSAGE oMessage);


	int GetNeighbourDetails(int nNeighbourID);
	int GetRoute(int nDestinationID);
	//Generate and Send Gateway Info
	void SendGateWayInfo(int nDestination);
	void SendGateWayInfoEx(int nDestinationID);
	// Generate and send Withdraw messages
	void DeleteRoutes(int nDeadID, int nMsgSrcID);
	//void DeleteRoutes(int nDeadID);

	void SendNewActivePath(int nNewActivePath);

	void GetRoutingTable(vector<ROUTE_TABLE> &ovecRouteTable){ovecRouteTable = m_vecRoutingTable;}

	void SendFullRoutingTable(int nNodeID);

	void SendData(int nDestinationID, char strMessage[DATA_MESSAGE_MAX], int nDataLength);

	bool EncodeMessage(char *strMessage, MESSAGE MessageInfo);
	bool DecodeMessage(char*  Message, MESSAGE& MessageInfo);

	// Node Info
	NODE_INFO m_NodeInfo;

	//Neigbour Info
	vector<NEIGBOUR_INFO> m_vecNeighbourInfo;

	// Data Store
	vector<DATASTORE> m_vecDataStore;
	void BackuptoDataStore(DATASTORE oDataStoreInfo);
	void RemoveFromDataStore(unsigned int nSeqNo);
	void ReSendFromDataStore();
	void printRoutingTable();

	// Routing Table
	vector<ROUTE_TABLE> m_vecRoutingTable;

	char strSendData[MESSAGE_LENGTH];
	char strReceivedData[MESSAGE_LENGTH];

	pthread_t tidReceUDP;
	pthread_attr_t attrReceiveUDP;

	pthread_t tidHelloMessage;
	pthread_attr_t attrHelloMessage;

	pthread_t tidResendDataStore;
	pthread_attr_t attrResendDataStore;

	struct hostent *h;
	struct sockaddr_in NeighAddr;
	struct sockaddr_in servaddr;
	socklen_t slen;

	int nSeqNo;
	int GetNextSeqNo(){return (++nSeqNo);};
	pthread_t _thread;

	CLogger *m_pLogger;
	//pthread_mutex_lock(&g_LockNeighbour); ??
	//pthread_mutex_unlock(&g_LockNeighbour); ??


};

#endif
